import tensorflow as tf
if tf.config.list_physical_devices('GPU'):
device_name=tf.test.gpu_device_name()
else:
device_name='/CPU:0'
import time
num_epochs=100
batch_size=64
image_size=(28, 28)
z_size=20
mode_z='uniform'
gen_hidden_layers=1
gen_hidden_size=100
disc_hidden_layers=1
disc_hidden_size=100
tf.random.set_seed(1)
np.random.seed(1)
if mode_z=='uniform':
fixed_z=tf.random.uniform(shape=(batch_size, z_size), minval=-1, maxval=1)
elif mode_z=='normal':
fixed_z=tf.random.normal(shape=(batch_size, z_size))
def create_samples(g_model, input_z):
g_output=g_model(input_z, training=False)
images=tf.reshape(g_output, (batch_size, *image_size))
return (images+1)/2.0
mnist_trainset=mnist['train']
mnist_trainset=mnist_trainset.map(lambda ex:preprocess(ex, mode=mode_z))
mnist_trainset=mnist_trainset.shuffle(10000)
mnist_trainset=mnist_trainset.batch(batch_size, drop_remainder=True)
with tf.device(device_name):
gen_model=make_generator_network(
num_hidden_layers=gen_hidden_layers,
num_hidden_units=gen_hidden_size,
num_output_units=np.prod(image_size))
gen_model.build(input_shape=(None, z_size))
disc_model=make_discriminator_network(
num_hidden_layers=disc_hidden_layers,
num_hidden_units=disc_hidden_size)
disc_model.build(input_shape=(None, np.prod(image_size)))
loss_fn=tf.keras.losses.BinaryCrossentropy(from_logits=True)
g_optimizer=tf.keras.optimizers.Adam()
d_optimizer=tf.keras.optimizers.Adam()
all_losses=[]
all_d_vals=[]
epoch_samples=[]
start_time=time.time()
for epoch in range(1, num_epochs+1):
epoch_losses, epoch_d_vals=[], []
for i, (input_z, input_real) in enumerate(mnist_trainset):
with tf.GradientTape() as g_tape:
g_output=gen_model(input_z)
d_logits_fake=disc_model(g_output, training=True)
labels_real=tf.ones_like(d_logits_fake)
g_loss=loss_fn(y_true=labels_real, y_pred=d_logits_fake)
g_grads=g_tape.gradient(g_loss, gen_model.trainable_variables)
g_optimizer.apply_gradients(grads_and_vars=zip(g_grads, gen_model.trainable_variables))
with tf.GradientTape() as d_tape:
d_logits_real=disc_model(input_real, training=True)
d_labels_real=tf.ones_like(d_logits_real)
d_loss_real=loss_fn(y_true=d_labels_real, y_pred=d_logits_real)
d_logits_fake=disc_model(g_output, training=True)
d_labels_fake=tf.zeros_like(d_logits_fake)
d_loss_fake=loss_fn(y_true=d_labels_fake, y_pred=d_logits_fake)
d_loss=d_loss_real+d_loss_fake
d_grads=d_tape.gradient(d_loss, disc_model.trainable_variables)
d_optimizer.apply_gradients(grads_and_vars=zip(d_grads, disc_model.trainable_variables))
epoch_losses.append((g_loss.numpy(), d_loss.numpy(), d_loss_real.numpy(), d_loss_fake.numpy()))
d_probs_real=tf.reduce_mean(tf.sigmoid(d_logits_real))
d_probs_fake=tf.reduce_mean(tf.sigmoid(d_logits_fake))
epoch_d_vals.append((d_probs_real.numpy(), d_probs_fake.numpy()))
all_losses.append(epoch_losses)
all_d_vals.append(epoch_d_vals)
print('에포크 {:03d} | 시간 {:.2f} min | 평균 손실 >> 생성자/판별자 {:.4f}/{:.4f} [판별자-진짜: {:.4f}] 판별자-가짜: {:.4f}]'.format(epoch, (time.time()-start_time)/60, *list(np.mean(all_losses[-1], axis=0))))
epoch_samples.append(create_samples(gen_model, fixed_z).numpy())